//; ---------------------------------------------------------------------------
//; Object 3A - "SONIC GOT THROUGH" title	card
//; ---------------------------------------------------------------------------

#include "gotthroughcard.h"

#include "../plcsystem.h"
#include "../sprite.h"
#include "../objectsystemNEWER.h"

static object *obj;

//EXTERN DEFINITIONS HERE
extern plc_buffer_index v_plc_buffer[0x10];

extern byte LevelOrder[];

extern byte v_zone;
extern byte v_act;
extern word v_lastlamp;
extern bool f_lockctrl;
extern word v_limitright2;
extern byte f_endactbonus;
extern word v_timebonus;
extern word v_ringbonus;
extern byte f_restart;

extern long v_vbla_count;
#define v_vbla_word (v_vbla_count & 0x0000FFFF)
#define v_vbla_byte (v_vbla_count & 0x000000FF)

byte f_bigring;

//; ---------------------------------------------------------------------------
//; Animation script - (OBJECT)
//; ---------------------------------------------------------------------------

//; ---------------------------------------------------------------------------
//; Sprite mappings - "SONIC HAS PASSED" title card
//; ---------------------------------------------------------------------------
extern byte M_Card_Oval[];
extern byte M_Card_Act1[];
extern byte M_Card_Act2[];
extern byte M_Card_Act3[];

byte M_Got_SonicHas[41] = { 8,			      //; SONIC HAS
		 0xF8,   5,    0, 0x3E, 0xB8,
		 0xF8,   5,    0, 0x32, 0xC8,
		 0xF8,   5,    0, 0x2E, 0xD8,
		 0xF8,   1,    0, 0x20, 0xE8,
		 0xF8,   5,    0,    8, 0xF0,
		 0xF8,   5,    0, 0x1C, 0x10,
		 0xF8,   5,    0,    0, 0x20,
		 0xF8,   5,    0, 0x3E, 0x30
};
byte M_Got_Passed[31] = {  6,			     //; PASSED
		 0xF8,   5,    0, 0x36, 0xD0,
		 0xF8,   5,    0,    0, 0xE0,
		 0xF8,   5,    0, 0x3E, 0xF0,
		 0xF8,   5,    0, 0x3E,    0,
		 0xF8,   5,    0, 0x10, 0x10,
		 0xF8,   5,    0,  0xC, 0x20
};
byte M_Got_Score[31] = {   6,		            //; SCORE
		 0xF8, 0xD,    1, 0x4A, 0xB0,
		 0xF8,   1,    1, 0x62, 0xD0,
		 0xF8,   9,    1, 0x64, 0x18,
		 0xF8, 0xD,    1, 0x6A, 0x30,
		 0xF7,   4,    0, 0x6E, 0xCD,
		 0xFF,   4, 0x18, 0x6E, 0xCD
};
byte M_Got_TBonus[36] = {  7,	                       //; TIME BONUS
		 0xF8, 0xD,    1, 0x5A, 0xB0,
		 0xF8, 0xD,    0, 0x66, 0xD9,
		 0xF8,   1,    1, 0x4A, 0xF9,
		 0xF7,   4,    0, 0x6E, 0xF6,
		 0xFF,   4, 0x18, 0x6E, 0xF6,
		 0xF8, 0xD, 0xFF, 0xF0,	0x28,
		 0xF8,   1,    1, 0x70, 0x48
};
byte M_Got_RBonus[36] = {  7,		                    //; RING BONUS
		 0xF8, 0xD,    1, 0x52, 0xB0,
		 0xF8, 0xD,    0, 0x66, 0xD9,
		 0xF8,   1,    1, 0x4A, 0xF9,
		 0xF7,   4,    0, 0x6E, 0xF6,
		 0xFF,   4, 0x18, 0x6E, 0xF6,
		 0xF8, 0xD, 0xFF, 0xF8,	0x28,
		 0xF8,   1,    1, 0x70, 0x48
};

byte *Map_Got[9] = { M_Got_SonicHas, M_Got_Passed, M_Got_Score, M_Got_TBonus, M_Got_RBonus, M_Card_Oval, M_Card_Act1, M_Card_Act2, M_Card_Act3 };
//Map_Got[] = {	dc.w M_Got_SonicHas-Map_Got
//		dc.w M_Got_Passed-Map_Got
//		dc.w M_Got_Score-Map_Got
//		dc.w M_Got_TBonus-Map_Got
//		dc.w M_Got_RBonus-Map_Got
//		dc.w M_Card_Oval-Map_Got
//		dc.w M_Card_Act1-Map_Got
//		dc.w M_Card_Act2-Map_Got
//		dc.w M_Card_Act3-Map_Got

//==========

void (*Got_Index[9])() = { Got_ChkPLC, Got_Move, Got_Wait, Got_TimeBonus, Got_Wait, Got_NextLevel, Got_Wait, Got_Move2, loc_C766 };

//GotThroughCard:					; XREF: Obj_Index
void GotThroughCard(object *_obj)
{
    obj = _obj;

    //moveq	#0,d0
    //move.b	obRoutine(a0),d0
    byte routine = obj->Routine/2;

    //move.w	Got_Index(pc,d0.w),d1
    //jmp	Got_Index(pc,d1.w)
    (*Got_Index[routine])();
}

//; ===========================================================================

#define got_mainX 0x30		//; position for card to display on
#define got_finalX 0x32		//; position for card to finish on
//; ===========================================================================

//Got_ChkPLC:	; Routine 0
void Got_ChkPLC()
{
    
    //tst.l	(v_plc_buffer).w ; are the pattern load cues empty?
    //beq.s	Got_Main	; if yes, branch
    //if (v_plc_buffer[0].val1 == 0)
    //{
        Got_Main();
    //}
		
}   //rts	

//; ===========================================================================
//		;    x-start,	x-main,	y-main,
//		;				routine, frame number

word Got_Config[28] = { 4,	0x124,	0xBC,			//; "SONIC HAS"
                                                   0x0200,

		    -0x120,	0x120,	0xD0,			//; "PASSED"
		 				   0x0201,

		     0x40C,	0x14C,	0xD6,			//; "ACT" 1/2/3
		 				   0x0206,

		     0x520,	0x120,	0xEC,			//; score
		     				   0x0202,

		     0x540,	0x120,	0xFC,			//; time bonus
		 				   0x0203,

		     0x560,	0x120,	0x10C,			//; ring bonus
		 				   0x0204,

		     0x20C,	0x14C,	0xCC,			//; oval
		  				0x0205
};

//Got_Main:
void Got_Main()
{
    //movea.l	a0,a1
    object *cardPiece = obj;    

    //lea	(Got_Config).l,a2
    word *config = Got_Config;

    //moveq	#6,d1
    long cardPieces = 6;

    //Got_Loop:
    for (;cardPieces >= 0;cardPieces--)
    {
        //move.b	#id_GotThroughCard,0(a1)
        cardPiece->ID = id_GotThroughCard;

	word startX = *(config++);
        //move.w	(a2),obX(a1)	; load start x-position
        cardPiece->X = startX;
       
	//move.w	(a2)+,got_finalX(a1) ; load finish x-position (same as start)
        ptrsetobjvariableword(got_finalX, cardPiece, startX);

	word mainX = *(config++);
        //move.w	(a2)+,got_mainX(a1) ; load main x-position
        ptrsetobjvariableword(got_mainX, cardPiece, mainX);

	//move.w	(a2)+,obScreenY(a1) ; load y-position
        cardPiece->ScreenY = *(config++);

	//move.b	(a2)+,obRoutine(a1)
        cardPiece->Routine = (*(config) & 0xFF00) >> 8;

	//move.b	(a2)+,d0
        byte frameNum = *(config++) & 0x00FF;

	//cmpi.b	#6,d0
        //bne.s	loc_C5CA
        if (frameNum == 6)
        {
	    //add.b	(v_act).w,d0	; add act number to frame number
            frameNum = frameNum + v_act;
        }

   	//loc_C5CA:
	//move.b	d0,obFrame(a1)
        cardPiece->Frame = frameNum;

	//move.l	#Map_Got,obMap(a1)
        cardPiece->Map = Map_Got;

	//move.w	#$8580,obGfx(a1)
        cardPiece->Gfx = 0x8580;

	//move.b	#0,obRender(a1)
        cardPiece->Render = 0;

	//lea	$40(a1),a1
        cardPiece = cardPiece + 1;

    } //dbf	d1,Got_Loop	; repeat 6 times
 
    Got_Move();
}

//Got_Move:	; Routine 2
void Got_Move()
{
    //moveq	#$10,d1		; set horizontal speed
    long hspeed = 16;

    //move.w	got_mainX(a0),d0
    word mainX = ptrgetobjvariableword(got_mainX, obj);

    //cmp.w	obX(a0),d0	; has item reached its target position?
    //beq.s	loc_C61A	; if yes, branch
    if (mainX != obj->X)
    {
        //bge.s	Got_ChgPos
        //neg.w	d1
        if (mainX < obj->X)
            hspeed = -hspeed;
		 
        //Got_ChgPos:
	//add.w	d1,obX(a0)	; change item's position
        obj->X = obj->X + hspeed;
 
	//loc_C5FE:			; XREF: loc_C61A
	//move.w	obX(a0),d0
        signed short cardX = obj->X;

	//bmi.s	locret_C60E
        if (cardX >= 0)
        {
	    //cmpi.w	#$200,d0	; has item moved beyond	$200 on	x-axis?
            //bcc.s	locret_C60E	; if yes, branch
            if (cardX <= 0x200)
            {
		//bra.w	DisplaySprite
                DisplaySprite(obj);
            }
        }

        //locret_C60E:
        //rts
    }
    else
    {
        //loc_C61A:				; XREF: Got_Move
        //cmpi.b	#$E,($FFFFD724).w
        if (false /*FFFFD724 == 0xE*/)
        {
		//beq.s	loc_C610
                loc_C610();
        }
        else
        {
	    //cmpi.b	#4,obFrame(a0)
            if (obj->Frame != 4)
            { 
                //bne.s	loc_C5FE
                //loc_C5FE:			; XREF: loc_C61A
	        //move.w	obX(a0),d0
                signed short cardX = obj->X;

	        //bmi.s	locret_C60E
                if (cardX >= 0)
                {
	            //cmpi.w	#$200,d0	; has item moved beyond	$200 on	x-axis?
                    //bcc.s	locret_C60E	; if yes, branch
                    if (cardX <= 0x200)
                    {
		        //bra.w	DisplaySprite
                        DisplaySprite(obj);
                    }
                }
            }
            else
            {
	        //addq.b	#2,obRoutine(a0)
                obj->Routine = obj->Routine + 2;

		//move.w	#180,obTimeFrame(a0) ; set time delay to 3 seconds
                obj->TimeFrame = 180;
            
                Got_Wait();
            }
        }
    }
}

//Got_Wait:	; Routine 4, 8, $C
void Got_Wait()
{
    //subq.w	#1,obTimeFrame(a0) ; subtract 1 from time delay
    obj->TimeFrame = obj->TimeFrame - 1;
   
    //bne.s	Got_Display
    if (obj->TimeFrame != 0) { Got_Display(); }
    else
    {
        //addq.b	#2,obRoutine(a0)
        obj->Routine = obj->Routine + 2;
    
        Got_Display();
    }
}

//Got_Display:
void Got_Display()
{
    //bra.w	DisplaySprite
    DisplaySprite(obj);
}

//; ==================================================
//; ===========================================================================

//loc_C610:				; XREF: loc_C61A
void loc_C610()
{
    //move.b	#$E,obRoutine(a0)
    obj->Routine = 0xE;

    //bra.w	Got_Move2
    Got_Move2();
}

//; ===========================================================================

//=========================

//Got_TimeBonus:	; Routine 6
void Got_TimeBonus()
{
    //bsr.w	DisplaySprite
    DisplaySprite(obj);

    //move.b	#1,(f_endactbonus).w ; set time/ring bonus update flag
    f_endactbonus = 1;

    //moveq	#0,d0
    long score = 0;

    //tst.w	(v_timebonus).w	; is time bonus	= zero?
    //beq.s	Got_RingBonus	; if yes, branch
    if (v_timebonus != 0)
    {
        //addi.w	#10,d0		; add 10 to score
        score = score + 0x10;

	//subi.w	#10,(v_timebonus).w ; subtract 10 from time bonus
        v_timebonus = v_timebonus - 10;
    }

    //Got_RingBonus:
    //tst.w	(v_ringbonus).w	; is ring bonus	= zero?
    //beq.s	Got_ChkBonus	; if yes, branch
    if (v_ringbonus !=0)
    {
        //addi.w	#10,d0		; add 10 to score
        score = score + 10;

	//subi.w	#10,(v_ringbonus).w ; subtract 10 from ring bonus
        v_ringbonus = v_ringbonus - 10;
    }

    //Got_ChkBonus:
    //tst.w	d0		; is there any bonus
    //bne.s	Got_AddBonus	; if yes, branch
    if (score == 0)
    {
        //sfx	sfx_Cash	; play "ker-ching" sound
        
	//addq.b	#2,obRoutine(a0)
        obj->Routine = obj->Routine + 2;
		
        //cmpi.w	#(id_SBZ<<8)+1,(v_zone).w
        //bne.s	Got_SetDelay
	//addq.b	#4,obRoutine(a0)

        //Got_SetDelay:
	//move.w	#180,obTimeFrame(a0) ; set time delay to 3 seconds
        obj->TimeFrame = 180;
    }

    //locret_C692:
    //rts	
    else
    {
        //Got_AddBonus:				; XREF: Got_ChkBonus
	//jsr	AddPoints
        //AddPoints();

	//move.b	(v_vbla_byte).w,d0
        byte vblank = v_vbla_byte;

	//andi.b	#3,d0
        byte _vblank = vblank & 3;

	//bne.s	locret_C692
        if (_vblank == 0) { 

	    //sfx	sfx_Switch,1	; play "blip" sound
            //Got_NextLevel();
        }
    }
}

//; ===========================================================================

//Got_NextLevel:	; Routine $A
void Got_NextLevel()
{
    //move.b	(v_zone).w,d0
    //andi.w	#7,d0
    word curzone = v_zone & 7;     //restricted to 7 zones

    //lsl.w	#3,d0
    word orderzoneindex = curzone * 8;

    //move.b	(v_act).w,d1
    //andi.w	#3,d1
    word curact = v_act & 3;       //restricted to 3 acts/zone

    //add.w	d1,d1
    word orderactindex = curact * 2;

    //add.w	d1,d0
    word orderindex = orderactindex + orderzoneindex;

    //move.w	LevelOrder(pc,d0.w),d0 ; load level from level order array
    
    byte nextzone = LevelOrder[(orderindex*2)];
    byte nextact = LevelOrder[(orderindex*2)+1];

    //move.w	d0,(v_zone).w	; set level number
    v_zone = nextzone;
    v_act = nextact;

    //tst.w	d0
    //bne.s	Got_ChkSS
    if (((v_zone<<8)+(v_act)) == 0)
    {
        //move.b	#id_Sega,(v_gamemode).w
        //v_gamemode = id_Sega;
	//bra.s	Got_Display2
        Got_Display2();
    }
    else
    {
    //; ===========================================================================

        //Got_ChkSS:				; XREF: Got_NextLevel
	//clr.b	(v_lastlamp).w	; clear	lamppost counter
        v_lastlamp = 0;

	//tst.b	(f_bigring).w	; has Sonic jumped into	a giant	ring?
        //beq.s	VBla_08A
        if (f_bigring != 0)
	{	             //; if not, branch
	    //move.b	#id_Special,(v_gamemode).w ; set game mode to Special Stage (10)
            //v_gamemode = id_Special;
            //bra.s	Got_Display2
            Got_Display2();
        }
        else
        {            //; ===========================================================================
            //VBla_08A:				; XREF: Got_ChkSS
	    //move.w	#1,(f_restart).w ; restart level
            f_restart = 1;
            
            Got_Display2();
        }
    }
}    
//Got_Display2:				; XREF: Got_NextLevel, Got_ChkSS
//		bra.w	DisplaySprite
void Got_Display2()
{
    DisplaySprite(obj);
}

//; ===========================================================================
//; ---------------------------------------------------------------------------
//; Level	order array
//; ---------------------------------------------------------------------------
//LevelOrder:	incbin	"misc\Level Order.bin"
//		even
//		zonewarning LevelOrder,8
//; ===========================================================================

//Got_Move2:	; Routine $E
void Got_Move2()
{
    //moveq	#$20,d1		; set horizontal speed
    long hspeed = 0x20;

    //move.w	got_finalX(a0),d0
    word finalX = ptrgetobjvariableword(got_finalX, obj);
 
    //cmp.w	obX(a0),d0	; has item reached its finish position?
    //beq.s	Got_SBZ2	; if yes, branch
    if (finalX != obj->X)
    {
        //bge.s	Got_ChgPos2
        if (finalX < obj->X)
        {
	    //neg.w	d1
            hspeed = -hspeed;
        }
	
        //Got_ChgPos2:
	//add.w	d1,obX(a0)	; change item's position
        obj->X = obj->X + hspeed;

	//move.w	obX(a0),d0
        signed short curX = obj->X;

	//bmi.s	locret_C748
        if (curX > 0)
        {
	    //cmpi.w	#$200,d0	; has item moved beyond	$200 on	x-axis?
	    //bcc.s	locret_C748	; if yes, branch
            if (curX < 0x200)
            {
	        //bra.w	DisplaySprite
                DisplaySprite(obj);
            }
        }
    }
    //; ===========================================================================
    //locret_C748:
    //rts	
    //; ===========================================================================
   {
       //Got_SBZ2:				; XREF: Got_Move2
       //cmpi.b	#4,obFrame(a0)
       //bne.w	DeleteObject
       if (obj->Frame != 4) { DeleteObject(obj); }
       else
       {
           //addq.b	#2,obRoutine(a0)
           obj->Routine = obj->Routine + 2;
 
	   //clr.b	(f_lockctrl).w	; unlock controls
           f_lockctrl = 0;

	   //music	bgm_FZ,1	; play FZ music
           //; ===========================================================================
           
           loc_C766();
       }
   }
}

//loc_C766:	; Routine $10
void loc_C766()
{
    //addq.w	#2,(v_limitright2).w
    v_limitright2 = v_limitright2 + 2;

    //cmpi.w	#$2100,(v_limitright2).w
    //beq.w	DeleteObject
    if (v_limitright2 == 0x2100) { DeleteObject(obj); }
		
    
    //rts
}	


